package it.uniroma2.dtk.main;

import it.uniroma2.dtk.dt.GenericDT;
import it.uniroma2.util.math.ArrayMath;
import it.uniroma2.util.tree.Tree;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;

import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.GnuParser;
import org.apache.commons.cli.HelpFormatter;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.OptionBuilder;
import org.apache.commons.cli.OptionGroup;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;

@SuppressWarnings("static-access")
public class DTBuilder {

	protected static Options options = new Options();
	
	static {
		options.addOption("lexicalized", false, "consider leaf nodes");
		options.addOption("pos", false, "use pos augmented labels for leaf nodes in (lexicalized) syntactic trees");
		options.addOption(OptionBuilder.withArgName("seed")
				.hasArg()
				.withDescription("use given random seed (default = 0)")
				.create("randomSeed"));
		options.addOption(OptionBuilder.withArgName("size")
				.hasArg()
				.withDescription("use given vector size (default = 4096)")
				.create("vectorSize"));
		options.addOption(OptionBuilder.withArgName("lambda")
				.hasArg()
				.withDescription("use given lambda to weight tree fragments (default = 1)")
				.create("lambda"));
		options.addOption(OptionBuilder.withArgName("input file")
				.hasArg()
				.withDescription("load trees (in Penn Treebank notation) from the given file")
				.isRequired()
				.create("input"));
		options.addOption(OptionBuilder.withArgName("output file")
				.hasArg()
				.withDescription("print distributed trees to the given file")
				.isRequired()
				.create("output"));
		OptionGroup type = new OptionGroup()
				.addOption(new Option("product", "use shuffled gamma-product as composition operation"))
				.addOption(new Option("convolution", "use shuffled convolution as compostion operation"));
		type.setRequired(true);
		options.addOptionGroup(type);
	}
	
	/**
	 * @param args
	 */
	public static void main(String[] args) {
		try {
			DTBuilder dtb = new DTBuilder(args);
			dtb.process();
		} catch (ParseException e) {
			System.err.println( "Parsing failed: " + e.getMessage() );
			HelpFormatter formatter = new HelpFormatter();
			formatter.printHelp( "DTBuilder", options );
		} catch (NumberFormatException e) {
			System.err.println( "Parsing numeric fields failed: " + e.getMessage() );
		} catch (Exception e) {
			e.printStackTrace();
		}
	}
	
	protected GenericDT dt = null;
	protected File inputFile = null;
	protected File outputFile = null;
	
	public DTBuilder(String[] args) throws ParseException, NumberFormatException, Exception {
		CommandLineParser parser = new GnuParser();
		CommandLine line = parser.parse(options, args);
		dt = new GenericDT(line.hasOption("randomSeed") ? Integer.parseInt(line.getOptionValue("randomSeed")) : 0, 
						line.hasOption("vectorSize") ? Integer.parseInt(line.getOptionValue("vectorSize")) : 4096, 
						line.hasOption("pos"), 
						line.hasOption("lexicalized"), 
						line.hasOption("product") ? GenericDT.Types.PRODUCT : GenericDT.Types.CONVOLUTION);
		dt.setLambda(line.hasOption("lambda") ? Double.parseDouble(line.getOptionValue("lambda")) : 1);
		inputFile = new File(line.getOptionValue("input"));
		outputFile = new File(line.getOptionValue("output"));
	}
	
	public void process() throws Exception {
		BufferedReader input = new BufferedReader(new FileReader(inputFile));
		FileWriter output = new FileWriter(outputFile);
		while (true) {
			String treeString = input.readLine();
			if (treeString == null)
				break;
			output.write(ArrayMath.arrayToString(dt.dt(Tree.fromPennTree(treeString))) + "\n");
			System.out.print('.');
		}
		System.out.println("Done");
		input.close();
		output.close();
	}

}
